package com.srx.gateway.filter;

import com.srx.openfeign.utils.TokenUtil;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.Arrays;
import java.util.List;
import java.util.Objects;

/**
 * 自定义全局过滤器类
 * <p>用于处理每个请求的前置逻辑，如身份验证和用户信息解析。</p>
 * @author 沈汝旭
 * @since   2025-10-18 10:54
 * @version 1.0
 */
@Component
@Order(-1)
public class CustomGlobalFilter implements GlobalFilter
{

	/**
	 * 空令牌标识，用于标识不需要令牌验证的请求
	 */
	private static final String NULL_TOKEN = "null";
	/**
	 * 白名单路径列表，这些路径不需要进行令牌验证
	 * 包括Swagger相关的API文档路径和静态资源路径
	 */
	private static final List<String> WHITE_LIST = Arrays.asList(
			"/v3/api-docs",
			"/swagger-ui.html",
			"/doc.html",
			"/swagger-resources",
			"/webjars"
	);



	/**
     * 自定义过滤器处理每个请求
     *
     * @param exchange 服务器Web交换对象，包含请求和响应
     * @param chain 过滤器链，用于执行下一个过滤器或路由到目标服务
     * @return Mono<Void> 表示异步处理完成的信号
     */
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain)
    {
        //获取常用变量
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();

	    String path = request.getURI().getPath();

	    // 如果请求路径在白名单里，直接放行
	    if (WHITE_LIST.stream().anyMatch(path::contains))
		{
		    return chain.filter(exchange);
	    }
	    else
	    {
			//获取token
			String token = request.getHeaders().getFirst("Authorization");
			//没有token-----非法请求
			if (token == null)
			{
			    // 设置重定向状态码
			    response.setStatusCode(HttpStatus.UNAUTHORIZED);
			    // 设置重定向地址
			    response.getHeaders().set("Location", "http://localhost:18080/page/error.html");
			    return response.setComplete();
			}
			else
			{
			    //如果此次操作不需要token，则直接放行
			    if (Objects.equals(token, NULL_TOKEN))
			    {
				    return chain.filter(exchange);
			    }
			    else
			    {
				    //解析token
				    Jws<Claims> claimsJws = TokenUtil.parseToken(token);
				    //为空表示过期
				    if (claimsJws == null)
				    {
					    // 设置重定向状态码
					    response.setStatusCode(HttpStatus.UNAUTHORIZED);
					    // 设置重定向地址
					    response.getHeaders().set("Location", "http://localhost:8080/page/error.html");
					    return response.setComplete();
				    }
				    //未过期
				    else
				    {
					    //获取本次操作的用户id
					    String userId = claimsJws.getPayload().get("userId", String.class);
					    ServerHttpRequest newRequest = request.mutate()
							    .header("userId", userId)
							    .build();
					    //构建新的ServerWebExchange实例
					    ServerWebExchange newExchange = exchange.mutate()
							    .request(newRequest)
							    .response(response)
							    .build();
					    return chain.filter(newExchange);
				    }
			    }
			}
	    }
    }

}
